package com.maltys.redission.raw;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Collections;

/**
 * @author malty
 */
@Data
@Component
public class ReentrantRedisLockV3 {
    @Autowired
    private RedisTemplate redisTemplate;
    private DefaultRedisScript<Long> lockScript;
    private DefaultRedisScript<Object> unlockScript;

    @PostConstruct
    private void init() {
        this.lockScript = new DefaultRedisScript<>();
        // 加载加锁的脚本
        lockScript = new DefaultRedisScript<>();
        this.lockScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("reentrant-lock.lua")));
        this.lockScript.setResultType(Long.class);
        // 加载释放锁的脚本
        unlockScript = new DefaultRedisScript<>();
        this.unlockScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("reentrant-unlock.lua")));
    }

    /**
     * 加锁操作
     *
     * @param key         key
     * @param lockName    value 可以使用uuid，将来用来验证是否是自己加的锁
     * @param releaseTime 过期时间
     * @return 是否成功获取锁
     */
    public Long tryLock(String lockName, long releaseTime, String key) {
        // 执行脚本
        return (Long) redisTemplate.execute(lockScript, Collections.singletonList(lockName), key, releaseTime);
    }

    /**
     * 解锁
     *
     * @param lockName
     * @param key
     */
    public void releaseLock(String lockName, String key) {
        redisTemplate.execute(unlockScript, Collections.singletonList(lockName), key);
    }
}
